#! /usr/bin/python
#-*- coding:utf-8 -*-

import os
import os.path
import codecs
import pdb
from optparse import OptionParser
import sys


usage = "usage: %prog -f from-code -t to-code -i input-path [-o output-path]"
version = "%prog 1.1"
codepath = "/home/wsl/python_study/w1/"
suffix = ['.cpp','.c','.h','.hpp','.txt','.sh','.py','.pl']
support_file_type = ['gb2312','utf8']
filelist = []
bom = False 


def flag_callback(option, opt_str, value, parser):
    print "support file type:"
    for i in suffix:
        print i

def parserDef():
    """
        parser definition
    """
    parser = OptionParser(usage=usage,version=version)
    parser.add_option("-f",
        "--from-code",
        action="store",
        dest="fromcode",
        type="string",
        metavar = "NAME",
        help="encoding of original text")  
    parser.add_option("-t",
        "--to-code",
        action="store",
        dest="tocode",
        type="string",
        metavar="NAME",
        help="encoding for output")
    parser.add_option("-i",
        "--input",
        action="store",
        dest="input",
        type="string",
        metavar="PATH",
        help="input path of file or folder"
        )
    parser.add_option("-o",
        "--output",
        action="store",
        dest="output",
        type="string",
        metavar="PATH",
        help="output path of file or folder"
        )
    parser.add_option("--list",
        action="callback",
        callback = flag_callback,
        metavar="LIST",
        help="list all support file type"
        )
    return parser

def parserArgs(parser):
    """
        arguments resolve    
    """
    (options,args) = parser.parse_args()
    fromcode = options.fromcode
    tocode = options.tocode
    input = options.input
    output = options.output

    if not fromcode or not tocode or not input:
        print usage
        sys.exit()
    if fromcode not in support_file_type or fromcode not in support_file_type:
        print "only support gb2312 and utf8"
        sys.exit()
    if fromcode == tocode:
        print "two codetype must be different"
        sys.exit()
    if output is None:
        output = input+'/'
    else:
        if(os.path.exists(output)):
            os.system('rm -r ' + output)
        os.system('cp -r '+input +' '+output)

    return (fromcode,tocode,output)

def translate(codepath):
    filenames = os.listdir(codepath)
    for fn in filenames:
        do_translate(codepath,fn)

def judgeFileType(filepath):
    """
        judge file codetype, just support utf-8 or gb2312    
    """
    i = 0
    #pdb.set_trace()
    for line in open(filepath):
        i = i+1
        if line[:3] == codecs.BOM_UTF8:
            global bom
            bom = True
            return "utf8"
        try:
            line.decode('gb2312')
        except UnicodeDecodeError:
            try:
                line.decode('utf8')
                return "utf8"
            except UnicodeDecodeError:
                print filepath#log here
                print i
                return "unknown"
    return "gb2312"

            

def decodePath(fromcode,tocode,inpath):
    """
        Traverse all file in path
    """
    if os.path.isdir(inpath):
        for root,dirs,files in os.walk(inpath):
            for f in files:
                filepath = os.path.join(root,f)
                [pre,suf] = os.path.splitext(filepath)
                if suf in suffix:
                    filelist.append(filepath)
    elif os.path.isfile(inpath):
            [pre,suf] = os.path.splitext(inpath)
            if suf in suffix:
                filelist.append(inpath)
    
    #pdb.set_trace()

    for f in filelist:
        codetype = judgeFileType(f)
        do_translate(f,codetype,fromcode,tocode)                      


def do_translate(filepath,codetype,fromcode,tocode):
    #pdb.set_trace()
    #print 'codetype in f:',codetype
    #print 'fromcode:',fromcode
    #print 'tocode:',tocode


    newpath = filepath+'.new'
    print 'Process file:',filepath

    if codetype != "unknown":
        #pdb.set_trace()
        if codetype == tocode and not bom :
            return

        fn = open(newpath,'w')
        i=0
        for line in open(filepath):
            i = i+1
            if i==1 and line[:3] == codecs.BOM_UTF8:
                line = line[3:]
            try:
                line2 = unicode(line,codetype)
                line2 = line2.encode(tocode)
                fn.write(line2)
            except (UnicodeDecodeError,UnicodeEncodeError):
                print "Error--->line is:", i
                fn.close()
                os.remove(newpath)
                return
        fn.close()
            
    tmppath = filepath+".tmp"
    os.rename(filepath,tmppath)
    os.rename(newpath,filepath)
    os.remove(tmppath)
        

if __name__ == '__main__':
    if len(sys.argv) == 1:
        print usage
        sys.exit()
    parser = parserDef()
    (fromcode,tocode,output) = parserArgs(parser)  

    decodePath(fromcode,tocode,output)






